# -*- coding: utf-8 -*-
"""
    werkzeug.useragents
    ~~~~~~~~~~~~~~~~~~~

    This module provides a helper to inspect user agent strings.  This module
    is far from complete but should work for most of the current browsers that
    are available.


    :copyright: 2007-2008 by Armin Ronacher.
    :license: BSD, see LICENSE for more details.
"""
import re


class UserAgentParser(object):
    """
    A simple user agent parser.  Used by the `UserAgent`.
    """

    platforms = (
        (r'darwin|mac|os\s*x', 'Mac'),
        ('win', 'Win'),
        (r'x11|lin(\b|ux)?', 'Linux'),
        ('(sun|i86)os', 'Solaris'),
        ('iphone', 'iPhone'),
        (r'nintendo\s+wii', 'Wii'),
        ('irix', 'Irix'),
        ('hp-?ux', 'hpux'),
        ('aix', 'aix'),
        ('sco|unix_sv', 'sco'),
        ('bsd', 'bsd'),
        ('amiga', 'amiga')
    )
    browsers = (
        ('googlebot', 'Google'),
        ('msnbot', 'MSN'),
        ('yahoo', 'Yahoo'),
        ('ask jeeves', 'Ask'),
        (r'aol|america\s+online\s+browser', 'AOL'),
        ('opera', 'OP'),
        ('firefox|firebird|phoenix|iceweasel', 'FF'),
        ('galeon', 'Galeon'),
        ('safari', 'SF'),
        ('webkit', 'Webkit'),
        ('camino', 'Camino'),
        ('konqueror', 'Konqueror'),
        ('k-meleon', 'kmeleon'),
        ('netscape', 'NS'),
        (r'msie|microsoft\s+internet\s+explorer', 'IE'),
        ('lynx', 'Lynx'),
        ('links', 'Links'),
        ('seamonkey|mozilla', 'seamonkey')
    )

    _browser_version_re = r'(?:%s)[/\sa-z(]*(\d+[.\da-z]+)?(?i)'
    _language_re = re.compile(
        r'(?:;\s*|\s+)(\b\w{2}\b(?:-\b\w{2}\b)?)\s*;|'
        r'(?:\(|\[|;)\s*(\b\w{2}\b(?:-\b\w{2}\b)?)\s*(?:\]|\)|;)'
    )

    def __init__(self):
        self.platforms = re.compile(r'|'.join(['(?P<%s>%s)' % (b, a) for a, b
                                    in self.platforms]), re.I)
        self.browsers = [(b, re.compile(self._browser_version_re % a))
                         for a, b in self.browsers]

    def __call__(self, user_agent):
        match = self.platforms.search(user_agent)
        if match is not None:
            for platform, value in match.groupdict().iteritems():
                if value:
                    break
        else:
            platform = None
        for browser, regex in self.browsers:
            match = regex.search(user_agent)
            if match is not None:
                version = match.group(1)
                break
        else:
            browser = version = None
        match = self._language_re.search(user_agent)
        if match is not None:
            language = match.group(1) or match.group(2)
        else:
            language = None
        return platform, browser, version, language


class UserAgent(object):
    """
    Represents a user agent.  Pass it a WSGI environment or an user agent
    string and you can inspect some of the details from the user agent
    string via the attributes.  The following attribute exist:

    -   `string`, the raw user agent string
    -   `platform`, the browser platform
    -   `browser`, the name of the browser
    -   `version`, the version of the browser
    -   `language`, the language of the browser
    """
    _parser = UserAgentParser()

    def __init__(self, environ_or_string):
        if isinstance(environ_or_string, dict):
            environ_or_string = environ_or_string.get('HTTP_USER_AGENT', '')
        self.string = environ_or_string
        self.platform, self.browser, self.version, self.language = \
            self._parser(environ_or_string)

    def to_header(self):
        return self.string

    def __str__(self):
        return self.string

    def __nonzero__(self):
        return bool(self.browser)

    def __repr__(self):
        return '<%s %r/%s>' % (
            self.__class__.__name__,
            self.browser,
            self.version
        )


# conceptionally this belongs in this module but because we want to lazily
# load the user agent module (which happens in wrappers.py) we have to import
# it afterwards.  The class itself has the module set to this module so
# pickle, inspect and similar modules treat the object as if it was really
# implemented here.
#from werkzeug.wrappers import UserAgentMixin
